#!/bin/bash

# Example usage:
# network.sh [172.16.1.1] [eth0]
VERSION="1.0.0"
set -e

# 判断函数，使用ip命令验证
is_ip_address() {
    local ip=$1
    # 使用grep和正则表达式匹配IP地址的格式
    if echo "$ip" | grep -E '^([0-9]{1,3}\.){3}[0-9]{1,3}$' > /dev/null; then
        return 0 # 符合IP地址格式则返回0
    else
        return 1
    fi
}

# Function to convert subnet mask to CIDR notation
subnet_to_cidr() {
    local IFS
    local -a octets
    local i=0
    local cidr=0
 
    IFS='.' read -r -a octets <<< "$1"
    for octet in "${octets[@]}"; do
        while [ $octet -gt 0 ]; do
            cidr=$((cidr + (octet & 1)))
            octet=$((octet >> 1))
        done
    done
    echo "$cidr"
}

help_dhcp() {
    echo " 
    Usage:  network dhcp

    Dynamically obtaining IP addresses by setting up the device's network settings.
    "
}

help_static() {
    echo " 
    Usage:  network static <ip> <mask> <gateway> <eth> 

    Set the device's network to static IP address settings.

    Parameters:
    ip              Set the IP address of the device
    mask            Set subnet mask
    gateway         Set ip for gateway
    eth             Default eth0
    "
}

version() {
    echo "Network version ${VERSION}"
}

# 帮助函数
help() {
    echo " 
    Flag shorthand -h has been deprecated, please use --help

    Usage:  ./network [OPTIONS] COMMAND

    Commands:
    dhcp        Dynamically obtaining IP addresses by setting up the device's network settings.
    static      Set the device's network to static IP address settings.
    
    Global Options:
    -v, --version           Print version information and quit.

    Run 'network COMMAND --help' for more information on a command.
    "
}

dhcp_enable() {
if grep -qi Bionic "/etc/os-release"; then
	cat <<-EOF > /etc/dhcpcd.conf
		# A sample configuration for dhcpcd.
		# See dhcpcd.conf(5) for details.

		# Allow users of this group to interact with dhcpcd via the control socket.
		#controlgroup wheel

		# Inform the DHCP server of our hostname for DDNS.
		hostname

		# Use the hardware address of the interface for the Client ID.
		#clientid
		# or
		# Use the same DUID + IAID as set in DHCPv6 for DHCPv4 ClientID as per RFC4361.
		# Some non-RFC compliant DHCP servers do not reply with this set.
		# In this case, comment out duid and enable clientid above.
		duid

		# Persist interface configuration when dhcpcd exits.
		persistent

		# Rapid commit support.
		# Safe to enable by default because it requires the equivalent option set
		# on the server to actually work.
		option rapid_commit

		# A list of options to request from the DHCP server.
		option domain_name_servers, domain_name, domain_search, host_name
		option classless_static_routes
		# Most distributions have NTP support.
		option ntp_servers
		# Respect the network MTU. This is applied to DHCP routes.
		option interface_mtu

		# A ServerID is required by RFC2131.
		require dhcp_server_identifier

		# Generate Stable Private IPv6 Addresses instead of hardware based ones
		slaac private
	EOF

	ip addr flush eth0
	systemctl daemon-reload
	systemctl restart dhcpcd.service
else
	echo "Re-enabling DHCP via NetworkManager for all network interfaces"

	cat <<-EOF > /etc/network/interfaces
		# interfaces(5) file used by ifup(8) and ifdown(8)
		# Include files from /etc/network/interfaces.d:
		source-directory /etc/network/interfaces.d
	EOF

	ip addr flush eth0
	service networking restart
fi    
}

static_addr_enable() {
ADDR=${1:-172.16.1.1}
MASK=${2:-255.255.0.0}
GATEWAY=${3:-${IP_ADDR%.*}.1}
ETH_DEV=${4:-eth0}
DNS="8.8.8.8, 8.8.4.4"

if ! is_ip_address "$MASK"; then
    echo "static addr enable return 1"
    exit 1
fi

cidr=$(subnet_to_cidr "$MASK")

if grep -qi Bionic "/etc/os-release"; then
	cat <<-EOF > /etc/dhcpcd.conf
		# A sample configuration for dhcpcd.
		# See dhcpcd.conf(5) for details.

		# Allow users of this group to interact with dhcpcd via the control socket.
		#controlgroup wheel

		# Inform the DHCP server of our hostname for DDNS.
		hostname

		# Use the hardware address of the interface for the Client ID.
		#clientid
		# or
		# Use the same DUID + IAID as set in DHCPv6 for DHCPv4 ClientID as per RFC4361.
		# Some non-RFC compliant DHCP servers do not reply with this set.
		# In this case, comment out duid and enable clientid above.
		duid

		# Persist interface configuration when dhcpcd exits.
		persistent

		# Rapid commit support.
		# Safe to enable by default because it requires the equivalent option set
		# on the server to actually work.
		option rapid_commit

		# A list of options to request from the DHCP server.
		option domain_name_servers, domain_name, domain_search, host_name
		option classless_static_routes
		# Most distributions have NTP support.
		option ntp_servers
		# Respect the network MTU. This is applied to DHCP routes.
		option interface_mtu

		# A ServerID is required by RFC2131.
		require dhcp_server_identifier

		# Generate Stable Private IPv6 Addresses instead of hardware based ones
		slaac private

		interface ${ETH_DEV}
		static ip_address=${ADDR}/${cidr} #这里用CIDR的格式配置地址
		static routers=${GATEWAY} #这里配置的是网关
		static domain_name_servers=${DNS} #这里配置域名服务器地址  
	EOF

	ip addr flush "$ETH_DEV"
	systemctl daemon-reload
	systemctl restart dhcpcd.service
    systemctl enable dhcpcd.service #设置开机自启动
else
	cat <<-EOF > /etc/network/interfaces
		auto lo
		iface lo inet loopback

		auto ${ETH_DEV}
		iface ${ETH_DEV} inet static
		address ${ADDR}
		netmask ${MASK}
	EOF

	ip addr flush ${ETH_DEV}
	service networking restart
fi
}

if [[ ${UID} -ne 0 ]]; then
	echo "This script must be run as root!"
	exit 1
fi

CMD=$1
if [ $CMD = 'static' ];then
    para=${2:-""}

    if [[ $para = '-h' || $para = '--help' ]];then
        help_static
    elif is_ip_address "$para"; then
        echo "Enable static ip addr ..."
        static_addr_enable $2 $3 $4 $5
        echo "Config completed!"
    else
        help_static
    fi
elif [ $CMD = 'dhcp' ];then
    para=${2:-""}
    if [[ $para = '-h' || $para = '--help' ]];then
        help_dhcp
    else
        echo "Enable DHCP ..."
        dhcp_enable
        echo "Config completed!"
    fi
elif [[ $CMD = '-v' || $CMD = '--version' ]];then
    version
else
    help
fi
